import { createVNode, render, VNode } from "vue";
import styles from "./Dropdow.module.scss";
export type DropOption = {
  el: HTMLElement;
  content: () => VNode;
};
export const DropDownItem = defineComponent({
  props: {
    label: {
      type: String,
      default: "",
    },
    icon: {
      type: Object as PropType<VNode>,
      default: null,
    },
    onClick: {
      type: Function,
      default: () => {},
    },
  },
  setup(props, { emit }) {
    const { icon, label, onClick } = props;
    const hide = inject<() => void>("hide");

    return () => {
      return (
        <div
          class={styles.dropdownItem}
          onClick={() => {
            if (hide) {
              hide();
            }
            onClick();
          }}
        >
          {icon}
          <span>{label}</span>
        </div>
      );
    };
  },
});
const DropComponent = defineComponent({
  props: {
    option: {
      type: Object as PropType<DropOption>,
    },
  },
  setup(props, { expose }) {
    const { option } = props;
    const state = reactive({
      isShow: false,
      option: props.option,
      top: 0,
      left: 0,
    });
    expose({
      showDialog(option: DropOption) {
        state.option = option;
        state.isShow = true;
        let { top, left, height, width } = option.el.getBoundingClientRect();
        state.top = top + height;
        state.left = left + width;
      },
      hideDialog() {
        state.isShow = false;
      },
    });
    provide("hide", () => (state.isShow = false));
    const classes = computed(() => [
      styles.dropdow,
      {
        [styles.dropdowIsShow]: state.isShow,
      },
    ]);
    const blockStyle = computed(() => {
      return {
        top: `${state.top}px`,
        left: `${state.left}px`,
      };
    });
    const el: Ref<HTMLDivElement | null> = ref(null);
    const onmoseDownDocument = (e: MouseEvent) => {
      let elH = el.value as HTMLDivElement;
      if (!elH.contains(e.target as Node)) {
        //如果点击的是dropdow的内部就什么都不做，点击的外部就关闭dropdowm
        state.isShow = false;
      }
    };
    onMounted(() => {
      //事件的传递行为是先捕获在冒泡
      //之前为了阻止事件传播给block都加了stopPropagation，
      document.body.addEventListener("mousedown", onmoseDownDocument, true);
    });
    onBeforeMount(() => {
      document.body.removeEventListener("mousedown", onmoseDownDocument, true);
    });
    return () => {
      return (
        <div class={classes.value} style={blockStyle.value} ref={el}>
          {option?.content()}
        </div>
      );
    };
  },
});
let vm: any;
export const $Dropdow = (option: DropOption) => {
  //手动挂载组件
  let el = document.createElement("div");
  if (!vm) {
    vm = createVNode(DropComponent, { option }); //将组件渲染成虚拟节点
    // 将组件渲染到el这个元素上
    render(vm, el);
    document.body.appendChild(el);
  }
  vm.component?.exposed?.showDialog(option);
};
$Dropdow.hideDialog = () => {
  if (vm) {
    vm.component?.exposed?.hideDialog();
  }
};
